#include <jni.h>
#include <string>
#include "my_dlfcn.h"
#include <dlfcn.h>
#include <android/log.h>
//#include "Substrate/CydiaSubstrate.h"

extern "C" {
#include <HookZz/include/hookzz.h>
}

#include <stdio.h>

#define LOGV(...)  ((void)__android_log_print(ANDROID_LOG_INFO, "HOOK", __VA_ARGS__))

ssize_t (*orig_hooked)(void *thiz, const void *buffer, size_t useSize, bool blocking);

ssize_t hooked_write(void *thiz, const void *buffer, size_t useSize, bool blocking) {

    LOGV("AudioTrack.write called, arguments: this ptr: %p, buffer ptr: %p, useSize: %d, blocking: %d",
         thiz, buffer, useSize, blocking);

    char *charPtr = (char *) buffer;

    if (useSize > 0) {
        for (int i = 0; i < useSize; i++) {
            // LOGV("Before hooked, buffer[%d]: %d", i, *(charPtr + i));

            *(charPtr + i) = 0;

        }
    }

    LOGV("After hooked, %d are set to 0", useSize);

    return orig_hooked(thiz, buffer, useSize, blocking);
}

extern "C"
JNIEXPORT void JNICALL
Java_weishu_me_hookaudio_AudioController_muteMode(JNIEnv *env, jclass type, jint api_level) {

    void *handle;
    void *audioTrack_write;

    bool _32bit = sizeof(void *) == 4;

    LOGV("32bit mode ? %d", _32bit);

    if (api_level <= 23) {
        // Android M and below, use system's dlsym
        handle = dlopen("media", RTLD_NOW);
        audioTrack_write = dlsym(handle, "_ZN7android10AudioTrack5writeEPKvjb");
    } else if (api_level <= 25) {
        // Android N, and NR1, use our dlsym
        if (_32bit) {
            handle = my_dlopen("/system/lib/libmedia.so", RTLD_NOW);
        } else {
            handle = my_dlopen("/system/lib64/libmedia.so", RTLD_NOW);
        }

        audioTrack_write = my_dlsym(handle, "_ZN7android10AudioTrack5writeEPKvjb");
    } else {
        // Android O and above, libaudoclient;
        if (_32bit) {
            if (_32bit) {
                handle = my_dlopen("/system/lib/libaudioclient.so", RTLD_NOW);
            } else {
                handle = my_dlopen("/system/lib64/libaudioclient.so", RTLD_NOW);
            }
        }
        audioTrack_write = my_dlsym(handle, "_ZN7android10AudioTrack5writeEPKvjb");
    }

    LOGV("AudioTrack.write address: %p", audioTrack_write);

    ZzHookReplace(audioTrack_write, (void *) hooked_write, (void **) &orig_hooked);
}